import * as utils from '../utils/index';
import shapeStyle from '../utils/defaultStyle';
import _ from 'lodash';
import Anchor from '../item/anchor';
const _util = require('@antv/util');

const nodeOptions = {
    options: {
        size: [180, 34],
        //外边框样式
        style: {
            fill: '#fff',
            stroke: '#778899',
            lineWidth: 1,
            radius: 5,
        },
        label: '未命名节点',
        labelCfg: {
            textAlign: 'start',
            textBaseline: 'top',
            fill: '#333',
            fontSize: 13,
            shadowBlur: 10,
            offset: 5,
        },
        preRect: {
            show: true,
            fill: '#778899',
        },
        logoIcon: {
            show: true,
            img: '',
            width: 16,
            height: 16,
            offset: 5,
        },
        stateIcon: {
            show: true,
            img: '',
            width: 20,
            height: 20,
            offset: -5,
            loading: false,
        },
    },
    shapeType: 'base-node',
    /**
     * @param  cfg  属性配置项，所有原始数据的属性都会传入进来
     * @param  group 组,装图形元素的 group
     */
    drawAnchor(cfg, group, excludeIndexs) {
        const bbox = group.getFirst().getBBox();
        try {
            this.getAnchorPoints(cfg).forEach((p, i) => {
                if (Array.isArray(excludeIndexs) && excludeIndexs.includes(i)) {
                    return;
                }
                const anchorContainer = group.addGroup();
                new Anchor({
                    group: anchorContainer,
                    index: i,
                    model: {
                        style: {
                            x: bbox.minX + bbox.width * p[0],
                            y: bbox.minY + bbox.height * p[1],
                        },
                    },
                });
                group.anchorShapes.push(anchorContainer);
            });
        } catch (error) {
            console.error(error, '错误的锚点绘制');
        }
    },
    initAnchor(cfg, group) {
        // 用来装锚点 item 的数组
        group.anchorShapes = [];
        //excludeIndexs 排除绘制锚点的索引，拖拽时调用规则
        group.showAnchor = (g, excludeIndexs) => {
            this.drawAnchor(cfg, g, excludeIndexs);
        };
        // 清除所有锚点的 item
        group.clearAnchor = (g) => {
            g.anchorShapes && g.anchorShapes.forEach((a) => a.remove());
            g.anchorShapes = [];
        };
        group.clearHotpotActived = (g) => {
            g.anchorShapes &&
                g.anchorShapes.forEach((a) => {
                    if (a.isAnchor) a.setHotspotActived(false);
                });
        };
        group.getAllAnchors = () => {
            return group.anchorShapes.map((c) => {
                c.filter((a) => a.isAnchor);
            });
        };
        group.getAnchor = (i) => {
            return group.anchorShapes.filter((a) => a.get('index') === i);
        };
    },

    draw(cfg, group) {
        const customOptions = this || {};
        const {
            style: defaultStyle,
            preRect: defaultPreRect,
            logoIcon: defaultLogoIcon,
            stateIcon: defaultStateIcon,
            labelCfg: defaultLabelCfg,
            label: defaultLabel,
        } = this.options;
        const {
            style: customStyle,
            preRect: customPreRect,
            logoIcon: customLogoIcon,
            stateIcon: customStateIcon,
            labelCfg: customLabelCfg,
            label: customLabel,
        } = customOptions;

        const size = this.getSize(cfg);
        const width = size[0];
        const height = size[1];
        const x = -width / 2;
        const y = -height / 2;
        let leftX = x;
        const rectStyle = _util.deepMix({}, defaultStyle, customStyle, cfg.style);

        //外边框 主要的 keyShape
        const keyShape = group.addShape('rect', {
            attrs: {
                x: x,
                y: y,
                width: width,
                height: height,
                ...rectStyle,
                // fill: 'rgba(0,0,0,0)' // todo
            },
            name: 'rect-shape',
        });

        // 左侧色条
        const preRect = _util.deepMix({}, defaultPreRect, customPreRect, cfg.preRect);
        if (preRect.show) {
            const preRectWidth = rectStyle.radius * 1.5;
            group.addShape('path', {
                attrs: {
                    path: [
                        ['M', x, y + rectStyle.radius],
                        ['L', x, y + height - rectStyle.radius],
                        ['A', rectStyle.radius, rectStyle.radius, 0, 0, 0, x + rectStyle.radius, y + height],
                        ['L', x + preRectWidth, y + height],
                        ['L', x + preRectWidth, y],
                        ['L', x + rectStyle.radius, y],
                        ['A', rectStyle.radius, rectStyle.radius, 0, 0, 0, x, y + rectStyle.radius],
                    ],
                    fill: preRect.fill,
                },
                name: 'preRect',
                draggable: true,
            });
            leftX += preRectWidth;
        }
        // 左侧默认logo
        const logoIcon = _util.deepMix({}, defaultLogoIcon, customLogoIcon, cfg.logoIcon);
        if (logoIcon.show) {
            leftX += logoIcon.offset;
            group.addShape('image', {
                attrs: {
                    img: logoIcon.img,
                    x: leftX,
                    y: y + (height - logoIcon.height) / 2,
                    width: logoIcon.width,
                    height: logoIcon.height,
                },
                draggable: true,
            });
            leftX += logoIcon.width;
        }

        //右侧状态图标
        const stateIcon = _util.deepMix({}, defaultStateIcon, customStateIcon, cfg.stateIcon);
        //loading状态需要
        this.statePosition = {
            x: x + width - logoIcon.offset,
            y: y + height / 2,
        };
        let labelMaxWidth = width - (leftX - x);
        if (stateIcon.show) {
            labelMaxWidth -= stateIcon.width + logoIcon.offset;
            if (!stateIcon.loading) {
                group.addShape('image', {
                    attrs: {
                        img: stateIcon.img,
                        x: x + width - stateIcon.width - logoIcon.offset,
                        y: y + (height - stateIcon.height) / 2,
                        width: stateIcon.width,
                        height: stateIcon.height,
                        isState: true,
                    },
                    draggable: true,
                });
            }
        }

        const labelCfg = _util.deepMix({}, defaultLabelCfg, customLabelCfg, cfg.labelCfg);
        const label = cfg.label || customLabel || defaultLabel;
        labelMaxWidth = Math.max(labelMaxWidth - labelCfg.offset * 2, 0);
        this.labelMaxWidth = labelMaxWidth;

        const fittingLabel = utils.suitableString(label, labelMaxWidth, labelCfg.fontSize);
        leftX += labelCfg.offset;
        // 名称文本
        group.addShape('text', {
            attrs: {
                text: fittingLabel,
                x: leftX,
                y: y + (height - labelCfg.fontSize) / 2 + 1,
                ...labelCfg,
            },
            className: 'rect-label',
            draggable: true,
        });

        this.initAnchor(cfg, group);

        return keyShape;
    },

    afterDraw(cfg, group) {
        const customOptions = this || {};
        const { stateIcon: defaultStateIcon } = this.options;
        const { stateIcon: customStateIcon } = customOptions;

        const stateIcon = _util.deepMix({}, defaultStateIcon, customStateIcon, cfg.stateIcon);
        if (stateIcon.show && stateIcon.loading) {
            const statePosition = this.statePosition;
            const leftX = statePosition.x - 26;
            const circle1 = group.addShape('circle', {
                attrs: {
                    x: leftX,
                    y: statePosition.y,
                    r: 3,
                    fill: '#9a9a9a',
                    opacity: 1,
                },
                name: 'circle-shape1',
            });
            const circle2 = group.addShape('circle', {
                attrs: {
                    x: leftX + 10,
                    y: statePosition.y,
                    r: 3,
                    fill: '#9a9a9a',
                    opacity: 1,
                },
                name: 'circle-shape2',
            });
            const circle3 = group.addShape('circle', {
                attrs: {
                    x: leftX + 20,
                    y: statePosition.y,
                    r: 3,
                    fill: '#9a9a9a',
                    opacity: 1,
                },
                name: 'circle-shape3',
            });

            circle1.animate(
                {
                    // 动画重复
                    repeat: true,
                    // 每一帧的操作，入参 ratio：这一帧的比例值（Number）。返回值：这一帧需要变化的参数集（Object）。
                    onFrame(ratio) {
                        return {
                            opacity: 0.3 + ratio * 0.7,
                        };
                    },
                },
                900
            );
            circle2.animate(
                {
                    // 动画重复
                    repeat: true,
                    // 每一帧的操作，入参 ratio：这一帧的比例值（Number）。返回值：这一帧需要变化的参数集（Object）。
                    onFrame(ratio) {
                        return {
                            opacity: 0.3 + ratio * 0.7,
                        };
                    },
                },
                900,
                'easeLinear',
                null,
                300
            );
            circle3.animate(
                {
                    // 动画重复
                    repeat: true,
                    // 每一帧的操作，入参 ratio：这一帧的比例值（Number）。返回值：这一帧需要变化的参数集（Object）。
                    onFrame(ratio) {
                        return {
                            opacity: 0.3 + ratio * 0.7,
                        };
                    },
                },
                900,
                'easeLinear',
                null,
                600
            );
        }
    },
    // 锚点
    getAnchorPoints(cfg) {
        if (!cfg || !cfg.anchorConfig)
            return [
                [0.5, 0],
                [0.5, 1],
            ];

        return [
            ...this._getSingleAnchorPoints(cfg.anchorConfig, 'top'),
            ...this._getSingleAnchorPoints(cfg.anchorConfig, 'bottom'),
            ...this._getSingleAnchorPoints(cfg.anchorConfig, 'left'),
            ...this._getSingleAnchorPoints(cfg.anchorConfig, 'right'),
        ];
    },
    _getSingleAnchorPoints(anchorConfig, type) {
        let singleAnchorPoints = [];
        if (anchorConfig && anchorConfig[type]) {
            const singleAnchorConfig = anchorConfig[type];
            const singleType = typeof singleAnchorConfig;
            if (singleType === 'number') {
                new Array(singleAnchorConfig).forEach((item, i) => {
                    const ratio = (i + 1) * (1 / (singleAnchorConfig + 1));
                    let coordinate;
                    switch (type) {
                        case 'top':
                            coordinate = [ratio, 0];
                            break;
                        case 'bottom':
                            coordinate = [ratio, 1];
                            break;
                        case 'left':
                            coordinate = [0, ratio];
                            break;
                        case 'right':
                            coordinate = [1, ratio];
                            break;
                        default:
                            break;
                    }
                    if (coordinate) {
                        singleAnchorPoints.push(coordinate);
                    }
                });
            } else if (Array.isArray(singleAnchorConfig)) {
                const size = singleAnchorConfig.length;
                singleAnchorConfig.forEach((item, i) => {
                    const ratio = (i + 1) * (1 / (size + 1));
                    let coordinate;
                    switch (type) {
                        case 'top':
                            coordinate = [ratio, 0];
                            break;
                        case 'bottom':
                            coordinate = [ratio, 1];
                            break;
                        case 'left':
                            coordinate = [0, ratio];
                            break;
                        case 'right':
                            coordinate = [1, ratio];
                            break;
                        default:
                            break;
                    }
                    if (coordinate) {
                        singleAnchorPoints.push(coordinate);
                        // singleAnchorPoints.push({
                        //     label: item.label,
                        //     coordinate
                        // });
                    }
                });
            }
        }
        return singleAnchorPoints;
    },
    update(cfg, item) {
        console.error('更新了节点 update');
        const group = item.getContainer();
        const customOptions = this || {};
        const { labelCfg: defaultLabelCfg, label: defaultLabel } = this.options;
        const { labelCfg: customLabelCfg, label: customLabel } = customOptions;

        const labelCfg = _util.deepMix({}, defaultLabelCfg, customLabelCfg, cfg.labelCfg);
        const label = cfg.label || customLabel || defaultLabel;
        const text = group.findByClassName('rect-label');
        const fittingLabel = utils.suitableString(label, this.labelMaxWidth, labelCfg.fontSize);
        if (text) {
            text.attr({
                text: fittingLabel,
                ...labelCfg,
            });
        }
        //如果需要再updateItem时更新其他元素，再根据需要做实现

        //更新的时候需要还原节点的状态，否则会导致状态的错误触发
        item.setState('show-anchor', false);
        item.setState('hover', false);
        item.setState('selected', false);
    },
    // 设置状态
    setState(name, value, item) {
        //
        const group = item.getContainer();

        const customOptions = this || {};
        const { style: defaultStyle, preRect: defaultPreRect } = this.options;
        const { style: customStyle, preRect: customPreRect } = customOptions;
        const rectStyle = _.merge({}, defaultStyle, customStyle);

        if (name === 'show-anchor') {
            // todo 锚点实现暂时有问题 21.3.16
            if (value) {
                group.showAnchor(group);
            } else {
                group.clearAnchor(group);
            }
        } else if (name === 'selected') {
            const rect = group.getChildByIndex(0);
            if (value) {
                rect.attr('fill', rectStyle.stroke);
            } else {
                rect.attr('fill', rectStyle.fill);
            }
        } else if (name === 'hover') {
            const rect = group.getChildByIndex(0);
            const text = group.getChildByIndex(1);
            if (value) {
                rect.attr('lineWidth', rectStyle.lineWidth + 1.5);
                rect.attr('stroke', rectStyle.stroke);
                rect.attr('cursor', shapeStyle.cursor.hoverNode);
                if (text) text.attr('cursor', shapeStyle.cursor.hoverNode);
            } else {
                rect.attr('lineWidth', rectStyle.lineWidth);
                rect.attr('stroke', rectStyle.stroke);
                rect.attr('cursor', 'default');
                if (text) text.attr('cursor', 'default');
            }
        } else if (name === 'warn') {
            const preRectStyle = _.merge({}, defaultPreRect, customPreRect);
            const preRect = group.find((item) => {
                return item.get('name') === 'preRect';
            });
            if (value) {
                preRect.attr('fill', '#FADB14');
            } else {
                preRect.attr('fill', preRectStyle.fill);
            }
        }
    },
};

export default function(G6) {
    G6.registerNode('base-node', nodeOptions, 'single-node');
}
